
# 从 math 模块导入 atan2 和 degrees 函数，用于角度计算
from math import atan2, degrees
# 从 qtpy 库导入 QtCore 模块，提供核心的非 GUI 功能
from qtpy import QtCore
# 从 qtpy 库导入 QtGui 模块，提供图形和用户界面相关功能
from qtpy import QtGui
# 从 qtpy.QtWidgets 模块导入 QStyle 类，用于访问和使用系统样式
from qtpy.QtWidgets import QStyle

# 从 src.UI.Canvas.UICommon 模块导入所有内容，提供 UI 相关的通用功能
from src.UI.Canvas.UICommon import *
# 从 src.Core.Common 模块导入所有内容，提供核心的通用功能
from src.Core.Common import *

# 从 src.UI.Utils.stylesheet 模块导入 editableStyleSheet 函数，用于获取可编辑的样式表
from src.UI.Utils.stylesheet import editableStyleSheet
# 从 src.UI.Utils.stylesheet 模块导入 Colors 类，用于管理颜色
from src.UI.Utils.stylesheet import Colors

# 定义无效节点的画笔颜色为红色
InvalidNodePenColor = Colors.Red
# 定义暴露属性的颜色为黄色
ExposedPropertiesColor = Colors.Yellow


# Determines how to paint the node
class NodePainter(object):
    """
    该类包含静态方法，用于确定如何绘制不同状态和类型的节点。
    """

    @staticmethod
    def drawDeprecated(node, painter, option, widget):
        """
        绘制已弃用节点的提示信息。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 检查节点是否已弃用
        if node.isDeprecated():
            # 获取当前画笔的字体
            font = painter.font()
            # 设置字体大小为 6
            font.setPointSize(6)
            # 将修改后的字体设置给画笔
            painter.setFont(font)
            # 获取节点的边界矩形
            textRect = node.boundingRect()
            # 设置矩形的顶部位置
            textRect.setTop(textRect.height() - 10)
            # 用指定颜色填充矩形
            painter.fillRect(textRect, Colors.Red.darker(130))
            # 在矩形中绘制文本，提示节点已弃用
            painter.drawText(
                textRect, QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, "Deprecated"
            )

    @staticmethod
    def drawExperimental(node, painter, option, widget):
        """
        绘制实验性节点的提示信息。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 检查节点是否为实验性节点
        if node.isExperimental():
            # 获取当前画笔的字体
            font = painter.font()
            # 设置字体大小为 6
            font.setPointSize(6)
            # 将修改后的字体设置给画笔
            painter.setFont(font)
            # 获取节点的边界矩形
            textRect = node.boundingRect()
            # 设置矩形的顶部位置
            textRect.setTop(textRect.height() - 10)
            # 用指定颜色填充矩形
            painter.fillRect(textRect, Colors.Yellow.darker(180))
            # 在矩形中绘制文本，提示节点为实验性节点
            painter.drawText(
                textRect, QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, "Experimental"
            )

    @staticmethod
    def drawResizeHandles(node, painter, option, widget):
        """
        绘制节点的调整大小手柄。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 检查节点是否可调整大小且未折叠
        if node.resizable and not node.collapsed:
            # 创建一个 QPen 对象
            pen = QtGui.QPen()
            # 获取节点的高度
            height = node.geometry().height()
            # 获取节点的宽度
            width = node.geometry().width()
            # 计算圆角半径的两倍
            rf = node.roundness * 2
            # 设置画笔的颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔的样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
            # 将画笔设置给绘制器
            painter.setPen(pen)

            # 绘制左侧调整条
            if node.resizeStrips[0]:
                painter.drawLine(0, rf / 2, 0, height - rf / 2)
            # 绘制顶部调整条
            if node.resizeStrips[1]:
                painter.drawLine(rf / 2, 0, width - rf / 2, 0)
            # 绘制右侧调整条
            if node.resizeStrips[2]:
                painter.drawLine(width, rf / 2, width, height - rf / 2)
            # 绘制底部调整条
            if node.resizeStrips[3]:
                painter.drawLine(rf / 2, height, width - rf / 2, height)

            # 绘制右下角调整条
            if node.resizeStrips[4]:
                painter.drawArc(width - rf, height - rf, rf, rf, 0, -90 * 16)

            # 绘制左下角调整条
            if node.resizeStrips[5]:
                painter.drawArc(0, height - rf, rf, rf, -90 * 16, -90 * 16)

            # 绘制左上角调整条
            if node.resizeStrips[6]:
                painter.drawArc(0, 0, rf, rf, 90 * 16, 90 * 16)

            # 绘制右上角调整条
            if node.resizeStrips[7]:
                painter.drawArc(width - rf, 0, rf, rf, 90 * 16, -90 * 16)

    @staticmethod
    def asCommentNode(node, painter, option, widget):
        """
        将节点绘制为注释节点。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 创建一个表示节点框架的矩形
        frame = QtCore.QRectF(QtCore.QPointF(0, 0), node.geometry().size())
        # 设置画笔为无画笔
        painter.setPen(QtCore.Qt.NoPen)
        # 设置画刷颜色为深灰色
        painter.setBrush(QtCore.Qt.darkGray)

        # 获取节点的背景颜色
        color = Colors.NodeBackgrounds
        # 检查节点是否被选中
        if node.isSelected():
            # 如果选中，将颜色变亮 150%
            color = color.lighter(150)

        # 设置画刷颜色为节点的颜色
        painter.setBrush(node.color)
        # 创建一个黑色的画笔，线宽为 0.75
        pen = QtGui.QPen(QtCore.Qt.black, 0.75)
        # 检查节点是否处于选中状态
        if option.state & QStyle.State_Selected:
            # 如果选中，设置画笔颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔样式为实线
            pen.setStyle(QtCore.Qt.SolidLine)
        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 绘制圆角矩形
        painter.drawRoundedRect(frame, node.roundness, node.roundness)

        # 再次检查节点是否处于选中状态
        if option.state & QStyle.State_Selected:
            # 如果选中，设置画笔颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
            # 将画笔宽度乘以 1.5
            pen.setWidth(pen.width() * 1.5)
        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 设置画刷为透明颜色
        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        # 再次绘制圆角矩形
        painter.drawRoundedRect(frame, node.roundness, node.roundness)
        # 绘制一条线
        painter.drawLine(
            frame.left() + 5, node.labelHeight, frame.right() - 5, node.labelHeight
        )
        # 调用绘制调整大小手柄的方法
        NodePainter.drawResizeHandles(node, painter, option, widget)

    @staticmethod
    def drawGroups(node, painter, option, widget):
        """
        绘制节点的组。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 定义输入组的偏移量
        inputsOffset = QtCore.QPointF(-2, 0)
        # 定义输出组的偏移量
        outputsOffset = QtCore.QPointF(2, 0)
        # 创建一个白色半透明的画笔，线宽为 0.5
        painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255, 200), 0.5))
        # 遍历输入组
        for grp in node.groups["input"].values():
            # 检查组是否处于悬停状态且已展开，并且组内有引脚
            if grp.hovered and grp.expanded:
                if grp.numPins() > 0:
                    # 获取组的左下角位置
                    grpPos = grp.geometry().bottomLeft()
                    # 获取组内最后一个引脚的左下角位置
                    lastPinPos = grp._pins[grp.numPins() - 1].geometry().bottomLeft()
                    # 绘制线条
                    painter.drawLine(grpPos, grpPos + inputsOffset)
                    painter.drawLine(grpPos + inputsOffset, lastPinPos + inputsOffset)
                    painter.drawLine(lastPinPos + inputsOffset, lastPinPos)

        # 遍历输出组
        for grp in node.groups["output"].values():
            # 检查组是否处于悬停状态且已展开，并且组内有引脚
            if grp.hovered and grp.expanded:
                if grp.numPins() > 0:
                    # 获取组的右下角位置
                    grpPos = grp.geometry().bottomRight()
                    # 获取组内最后一个引脚的右下角位置
                    lastPinPos = grp._pins[grp.numPins() - 1].geometry().bottomRight()
                    # 绘制线条
                    painter.drawLine(grpPos, grpPos + outputsOffset)
                    painter.drawLine(grpPos + outputsOffset, lastPinPos + outputsOffset)
                    painter.drawLine(lastPinPos + outputsOffset, lastPinPos)

    @staticmethod
    def default(node, painter, option, widget):
        """
        以默认方式绘制节点。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 创建一个表示节点框架的矩形
        frame = QtCore.QRectF(QtCore.QPointF(0, 0), node.geometry().size())
        # 获取画布的细节级别
        lod = node.canvasRef().getCanvasLodValueFromCurrentScale()
        # 获取样式表中节点切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().NodeSwitch[0]

        # 获取节点的颜色
        color = node.color

        # 设置颜色的透明度为 230
        color.setAlpha(230)
        # 检查节点是否被选中
        if node.isSelected():
            # 如果选中，将颜色变亮 150%
            color = color.lighter(150)
        # 检查节点是否为临时节点
        if node.isTemp:
            # 如果是临时节点，将颜色变亮 50%，并设置透明度为 50
            color = color.lighter(50)
            color.setAlpha(50)

        # 创建一个画刷对象
        br = QtGui.QBrush(color)
        # 设置画刷给绘制器
        painter.setBrush(br)

        # 创建一个黑色的画笔，线宽为 0.5
        pen = QtGui.QPen(QtCore.Qt.black, 0.5)
        # 设置画笔为无画笔
        painter.setPen(QtCore.Qt.NoPen)

        # 创建一个去除边距的矩形
        r = frame.marginsRemoved(QtCore.QMarginsF(3, 3, 3, 3))
        # 根据细节级别选择绘制圆角矩形或普通矩形
        if lod < SWITCH_LOD:
            painter.drawRoundedRect(r, node.roundness, node.roundness)
        else:
            painter.drawRect(r)

        # 创建一个空的画刷对象
        br = QtGui.QBrush()
        # 设置画刷给绘制器
        painter.setBrush(br)
        # 检查节点是否需要绘制标签
        if node.drawlabel:
            # 创建一个表示标签区域的矩形
            lr = QtCore.QRectF(r)
            # 设置标签区域的高度
            lr.setHeight(node.labelHeight + NodeDefaults().CONTENT_MARGINS / 2)
            # 获取节点头部的颜色
            headColor = node.headColor
            # 检查节点是否为临时节点
            if node.isTemp:
                # 如果是临时节点，将头部颜色变亮 50%，并设置透明度为 50
                headColor = headColor.lighter(50)
                headColor.setAlpha(50)
            # 根据细节级别选择绘制路径或填充矩形
            if lod < SWITCH_LOD:
                # 创建一个路径对象
                path = QtGui.QPainterPath()
                # 设置路径的填充规则
                path.setFillRule(QtCore.Qt.WindingFill)
                # 向路径中添加圆角矩形
                path.addRoundedRect(lr, node.roundness, node.roundness)
                # 调整矩形的位置
                lr.setY(lr.y() + node.roundness)
                # 检查节点是否未折叠
                if not node.collapsed:
                    # 如果未折叠，向路径中添加矩形
                    path.addRect(lr)
                # 用头部颜色填充路径
                painter.fillPath(path, headColor)
            else:
                # 用头部颜色填充矩形
                painter.fillRect(lr, headColor)

        # 检查节点是否满足特定条件
        if (
                not node.isCallable()
                and node._rawNode.bCacheEnabled
                or node._rawNode.__class__.__name__ == "graphOutputs"
        ):
            # 调用设置画笔颜色的方法
            NodePainter.setPenColor(node, painter, pen)

        # 检查节点是否无效
        if not node.isValid():
            # 如果无效，设置画笔颜色为无效节点的颜色
            pen.setColor(InvalidNodePenColor)
            # 设置画笔样式为节点错误时的画笔样式
            pen.setStyle(node.optPenErrorType)
            # 将画笔宽度乘以 1.5
            pen.setWidth(pen.width() * 1.5)

        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 设置画刷为透明颜色
        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        # 根据细节级别选择绘制圆角矩形或普通矩形
        if lod < SWITCH_LOD:
            painter.drawRoundedRect(r, node.roundness, node.roundness)
        else:
            painter.drawRect(r)

        # 检查节点是否将输入暴露给复合节点
        if node.bExposeInputsToCompound:
            # 设置字体为 Arial，字号为 4
            painter.setFont(QtGui.QFont("Arial", 4))
            # 设置画笔颜色为暴露属性的颜色
            pen.setColor(ExposedPropertiesColor)
            # 将画笔设置给绘制器
            painter.setPen(pen)
            # 创建一个去除边距的矩形
            rtext = frame.marginsRemoved(QtCore.QMarginsF(5, 5, 5, 5))
            # 在矩形中绘制文本
            painter.drawText(rtext, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom, "exposing to compound")

            # 调用绘制选中状态的方法
        NodePainter.drawSelected(node, painter, pen, option, lod, SWITCH_LOD, frame)
        # 调用绘制调整大小手柄的方法
        NodePainter.drawResizeHandles(node, painter, option, widget)
        # 调用绘制组的方法
        NodePainter.drawGroups(node, painter, option, widget)
        # 调用绘制已弃用节点提示的方法
        NodePainter.drawDeprecated(node, painter, option, widget)
        # 调用绘制实验性节点提示的方法
        NodePainter.drawExperimental(node, painter, option, widget)

    @staticmethod
    def drawSelected(node, painter, pen, option, lod, SWITCH_LOD, r):
        """
        绘制节点的选中状态。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param pen: 画笔对象
        :param option: 绘制选项
        :param lod: 画布的细节级别
        :param SWITCH_LOD: 样式表中节点切换的细节级别阈值
        :param r: 表示节点框架的矩形
        """
        # 保存画笔的原始宽度
        prevWidth = pen.width()
        # 检查节点是否处于选中状态
        if option.state & QStyle.State_Selected:
            # 如果选中，设置画笔颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
            # 将画笔宽度乘以 1.5
            pen.setWidth(pen.width() * 1.5)
            # 将画笔设置给绘制器
            painter.setPen(pen)
            # 设置画刷为透明颜色
            painter.setBrush(QtGui.QColor(0, 0, 0, 0))
            # 根据细节级别选择绘制圆角矩形或普通矩形
            if lod < SWITCH_LOD:
                painter.drawRoundedRect(r, node.roundness * 1.5, node.roundness * 1.5)
            else:
                painter.drawRect(r)
        # 恢复画笔的原始宽度
        pen.setWidth(prevWidth)

    @staticmethod
    def setPenColor(node, painter, pen):
        """
        根据节点的状态设置画笔的颜色。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param pen: 画笔对象
        """
        # 保存画笔的原始宽度
        prevWidth = pen.width()
        # 检查节点是否正在计算
        if node.computing:
            # 如果正在计算，设置画笔颜色为黄色
            pen.setColor(Colors.Yellow)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
            # 将画笔宽度乘以 1.5
            pen.setWidth(prevWidth * 1.5)
        # 检查节点的原始节点是否为脏数据
        elif node._rawNode.isDirty():
            # 如果是脏数据，设置画笔颜色为橙色
            pen.setColor(Colors.Orange)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
        else:
            # 否则，设置画笔颜色为绿色
            pen.setColor(Colors.Green)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)

        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 恢复画笔的原始宽度
        pen.setWidth(prevWidth)

    @staticmethod
    def asVariableGetter(node, painter, option, widget):
        """
        将节点绘制为变量获取器节点。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 设置画笔为无画笔
        painter.setPen(QtCore.Qt.NoPen)
        # 设置画刷颜色为深灰色
        painter.setBrush(QtCore.Qt.darkGray)

        # 获取节点的颜色
        color = node.color
        # 检查节点是否被选中
        if node.isSelected():
            # 如果选中，将颜色变亮 150%
            color = color.lighter(150)

        # 创建一个径向渐变对象
        linearGrad = QtGui.QRadialGradient(QtCore.QPointF(40, 40), 300)
        # 设置渐变的起始颜色
        linearGrad.setColorAt(0, color)
        # 设置渐变的结束颜色
        linearGrad.setColorAt(1, color.lighter(180))
        # 创建一个画刷对象
        br = QtGui.QBrush(linearGrad)
        # 设置画刷给绘制器
        painter.setBrush(br)
        # 创建一个黑色的画笔，线宽为 0.5
        pen = QtGui.QPen(QtCore.Qt.black, 0.5)
        # 检查节点是否处于选中状态
        if option.state & QStyle.State_Selected:
            # 如果选中，设置画笔颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 绘制圆角矩形
        painter.drawRoundedRect(node.boundingRect(), node.roundness, node.roundness)
        # 设置字体为节点的名称字体
        painter.setFont(node.nodeNameFont)
        # 创建一个白色的画笔，线宽为 0.5
        painter.setPen(QtGui.QPen(QtCore.Qt.white, 0.5))
        # 获取节点的边界矩形
        textRect = node.boundingRect()
        # 设置矩形的宽度
        textRect.setWidth(textRect.width() - 10)
        # 在矩形中绘制节点变量的名称
        painter.drawText(
            textRect, QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, node.var.name
        )

    @staticmethod
    def asRerouteNode(node, painter, option, widget):
        """
        将节点绘制为重定向节点。

        :param node: 要绘制的节点对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 获取节点的颜色
        color = node.color
        # 设置颜色的透明度为 255
        color.setAlpha(255)
        # 将颜色变亮 100%
        color = color.lighter(100)
        # 检查节点是否为临时节点
        if node.isTemp:
            # 如果是临时节点，将颜色变亮 50%，并设置透明度为 50
            color = color.lighter(50)
            color.setAlpha(50)
        # 创建一个径向渐变对象
        linearGrad = QtGui.QRadialGradient(QtCore.QPointF(40, 40), 300)
        # 设置渐变的起始颜色
        linearGrad.setColorAt(0, color)
        # 设置渐变的结束颜色
        linearGrad.setColorAt(1, color.lighter(180))
        # 创建一个画刷对象
        br = QtGui.QBrush(linearGrad)
        # 设置画刷给绘制器
        painter.setBrush(br)

        # 创建一个黑色的画笔，线宽为 0.75
        pen = QtGui.QPen(QtCore.Qt.black, 0.75)
        # 保存画笔的原始宽度
        width = pen.width()
        # 检查节点是否处于选中状态
        if option.state & QStyle.State_Selected:
            # 如果选中，设置画笔颜色为样式表中的主颜色
            pen.setColor(editableStyleSheet().MainColor)
            # 设置画笔样式为节点选中时的画笔样式
            pen.setStyle(node.optPenSelectedType)
            # 将画笔宽度乘以 1.5
            pen.setWidth(width * 1.5)
        # 将画笔设置给绘制器
        painter.setPen(pen)
        # 绘制椭圆
        painter.drawEllipse(
            node.boundingRect().center(),
            node.drawRect.width() / 2,
            node.drawRect.width() / 2,
        )


# Determines how to paint a pin
class PinPainter(object):
    """
    该类包含静态方法，用于确定如何绘制不同类型的引脚。
    """
    # 定义执行引脚的画笔，颜色为白色，线宽为 0.5，线型为实线
    _execPen = QtGui.QPen(Colors.White, 0.5, QtCore.Qt.SolidLine)
    # 定义值引脚名称的画笔，颜色为白色，线宽为 0.5，线型为实线
    _valuePinNamePen = QtGui.QPen(Colors.White, 0.5, QtCore.Qt.SolidLine)
    # 定义组引脚的画笔，颜色为绝对黑色，线宽为 0.5，线型为实线
    _groupPen = QtGui.QPen(Colors.AbsoluteBlack, 0.5, QtCore.Qt.SolidLine)

    @staticmethod
    def asValuePin(pin, painter, option, widget):
        """
        将引脚绘制为值引脚。

        :param pin: 要绘制的引脚对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 获取引脚所属节点的画布细节级别
        lod = pin.owningNode().canvasRef().getCanvasLodValueFromCurrentScale()
        # 获取样式表中引脚切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().PinSwitch[0]

        # 创建一个表示引脚框架的矩形
        frame = QtCore.QRectF(QtCore.QPointF(0, 0), pin.geometry().size())

        # 计算引脚半径的一半
        halfPinSize = pin.pinSize / 2

        # 检查细节级别是否小于阈值且引脚标签未隐藏
        if lod < SWITCH_LOD and not pin.bLabelHidden:
            # 设置字体为引脚的字体
            painter.setFont(pin._font)
            # 计算引脚显示名称的文本宽度
            textWidth = QtGui.QFontMetrics(painter.font()).horizontalAdvance(
                pin.displayName()
            )
            # 计算引脚显示名称的文本高度
            textHeight = QtGui.QFontMetrics(painter.font()).height()
            # 计算文本的 x 坐标
            x = 1 + pin.pinSize + halfPinSize
            # 检查引脚的方向是否为输出
            if pin.direction == PinDirection.Output:
                # 如果是输出引脚，重新计算 x 坐标
                x = frame.width() - textWidth - pin.pinSize - 1
            # 计算文本的 y 坐标
            yCenter = textHeight - textHeight / 3
            # 创建一个画笔，颜色为引脚标签颜色，线宽为 0.5，线型为实线
            painter.setPen(QtGui.QPen(
                pin.labelColor, 0.5, QtCore.Qt.SolidLine))
            # 在指定位置绘制引脚显示名称
            painter.drawText(x, yCenter, pin.displayName())

        # 获取引脚的中心点
        pinCenter = pin.pinCenter()
        # 创建一个径向渐变对象
        radialGrad = QtGui.QRadialGradient(
            pinCenter.x(), pinCenter.y() - 0.3, halfPinSize * 0.8
        )
        # 检查引脚是否有连接
        if not pin._rawPin.hasConnections():
            # 如果没有连接，设置渐变颜色
            radialGrad.setColorAt(0, pin.color().darker(280))
            radialGrad.setColorAt(0.5, pin.color().darker(280))
            radialGrad.setColorAt(0.65, pin.color().lighter(130))
            radialGrad.setColorAt(1, pin.color().lighter(70))
        else:
            # 如果有连接，设置渐变颜色
            radialGrad.setColorAt(0, pin.color())
            radialGrad.setColorAt(1, pin.color())

        # 设置画笔为无画笔
        painter.setPen(QtCore.Qt.NoPen)
        # 检查引脚是否处于悬停状态
        if pin.hovered:
            # 如果悬停，设置渐变颜色
            radialGrad.setColorAt(1, pin.color().lighter(200))
            # 设置画刷为半透明灰色
            painter.setBrush(QtGui.QColor(128, 128, 128, 30))
            # 绘制圆角矩形
            painter.drawRoundedRect(frame, 3, 3)
        # 设置画刷为径向渐变
        painter.setBrush(radialGrad)
        # 绘制椭圆
        painter.drawEllipse(
            pinCenter.x() - halfPinSize,
            pinCenter.y() - halfPinSize,
            pin.pinSize,
            pin.pinSize,
        )

    @staticmethod
    def asExecPin(pin, painter, option, widget):
        """
        将引脚绘制为执行引脚。

        :param pin: 要绘制的引脚对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 获取引脚所属节点的画布细节级别
        lod = pin.owningNode().canvasRef().getCanvasLodValueFromCurrentScale()
        # 获取样式表中引脚切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().PinSwitch[0]
        # 创建一个表示引脚框架的矩形
        frame = QtCore.QRectF(QtCore.QPointF(0, 0), pin.geometry().size())
        # 计算矩形宽度的一半
        w = frame.width() / 2
        # 计算矩形高度的一半
        h = frame.height() / 2
        # 计算引脚半径的一半
        halfPinSize = pin.pinSize / 2
        # 设置字体为引脚的字体
        painter.setFont(pin._font)
        # 设置画笔为执行引脚的画笔
        painter.setPen(PinPainter._execPen)

        # 检查细节级别是否小于阈值且引脚标签未隐藏
        if lod < SWITCH_LOD and not pin.bLabelHidden:
            # 计算引脚显示名称的文本宽度
            textWidth = QtGui.QFontMetrics(painter.font()).horizontalAdvance(
                pin.displayName()
            )
            # 计算引脚显示名称的文本高度
            textHeight = QtGui.QFontMetrics(painter.font()).height()
            # 计算文本的 x 坐标
            x = 1 + pin.pinSize + halfPinSize
            # 检查引脚的方向是否为输出
            if pin.direction == PinDirection.Output:
                # 如果是输出引脚，重新计算 x 坐标
                x = frame.width() - textWidth - pin.pinSize - 1
            # 计算文本的 y 坐标
            yCenter = textHeight - textHeight / 3
            # 创建一个画笔，颜色为引脚标签颜色，线宽为 0.5，线型为实线
            painter.setPen(QtGui.QPen(
                pin.labelColor, 0.5, QtCore.Qt.SolidLine))
            # 在指定位置绘制引脚显示名称
            painter.drawText(x, yCenter, pin.displayName())

        # 检查引脚是否有连接
        if pin._rawPin.hasConnections():
            # 如果有连接，设置画刷颜色为引脚颜色
            painter.setBrush(QtGui.QBrush(pin.color()))
        else:
            # 如果没有连接，设置画刷为无画刷
            painter.setBrush(QtCore.Qt.NoBrush)
        # 获取引脚的中心点
        pinCenter = pin.pinCenter()
        # 计算 x 偏移量
        xOffset = (
            pinCenter.x() - pin.pinSize
            if pin.direction == PinDirection.Input
            else pinCenter.x() - pin.pinSize * 0.8
        )
        # 创建一个多边形对象
        arrow = QtGui.QPolygonF(
            [
                QtCore.QPointF(2, 0.0),
                QtCore.QPointF(2 + pin.pinSize / 2.0, 0.0),
                QtCore.QPointF(2 + pin.pinSize, pin.pinSize / 2.0),
                QtCore.QPointF(2 + pin.pinSize / 2.0, pin.pinSize),
                QtCore.QPointF(2, pin.pinSize),
            ]
        ).translated(xOffset, 1)
        # 绘制多边形
        painter.drawPolygon(arrow)
        # 检查引脚是否处于悬停状态
        if pin.hovered:
            # 如果悬停，设置画笔为无画笔
            painter.setPen(QtCore.Qt.NoPen)
            # 设置画刷为半透明灰色
            painter.setBrush(QtGui.QColor(128, 128, 128, 30))
            # 绘制圆角矩形
            painter.drawRoundedRect(frame, 3, 3)

    @staticmethod
    def asGroupPin(pin, painter, option, widget):
        """
        将引脚绘制为组引脚。

        :param pin: 要绘制的引脚对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 设置画笔为组引脚的画笔
        painter.setPen(PinPainter._groupPen)
        # 设置画刷颜色为绝对黑色
        painter.setBrush(QtGui.QBrush(Colors.AbsoluteBlack))
        # 检查引脚是否展开
        if not pin.expanded:
            # 如果未展开，创建一个多边形对象
            arrow = QtGui.QPolygonF(
                [
                    QtCore.QPointF(0.0, 0.0),
                    QtCore.QPointF(pin.pinSize, pin.pinSize / 2.0),
                    QtCore.QPointF(0, pin.pinSize),
                ]
            )
        else:
            # 如果展开，创建一个多边形对象
            arrow = QtGui.QPolygonF(
                [
                    QtCore.QPointF(pin.pinSize / 2, pin.pinSize),
                    QtCore.QPointF(0, 0),
                    QtCore.QPointF(pin.pinSize, 0),
                ]
            )
        # 绘制多边形
        painter.drawPolygon(arrow)

    @staticmethod
    def asArrayPin(pin, painter, option, widget):
        """
        将引脚绘制为数组引脚。

        :param pin: 要绘制的引脚对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 获取引脚所属节点的画布细节级别
        lod = pin.owningNode().canvasRef().getCanvasLodValueFromCurrentScale()
        # 获取样式表中引脚切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().PinSwitch[0]
        # 定义网格大小
        gridSize = 3
        # 计算每个网格单元的宽度
        cellW = pin.pinSize / gridSize
        # 计算每个网格单元的高度
        cellH = pin.pinSize / gridSize
        # 获取引脚的中心点
        pinCenter = pin.pinCenter()
        # 计算引脚半径的一半
        halfPinSize = pin.pinSize / 2

        # 设置画刷颜色为引脚颜色
        painter.setBrush(QtGui.QBrush(pin.color()))
        # 创建一个黑色的画笔，线宽为 0.2
        painter.setPen(QtGui.QPen(QtCore.Qt.black, 0.2))
        # 遍历网格的行和列
        for row in range(gridSize):
            for column in range(gridSize):
                # 计算每个网格单元的 x 坐标
                x = row * cellW + pinCenter.x() - halfPinSize
                # 计算每个网格单元的 y 坐标
                y = column * cellH + pinCenter.y() - halfPinSize
                # 绘制矩形
                painter.drawRect(x, y, cellW, cellH)

        # 检查细节级别是否小于阈值且引脚标签未隐藏
        if lod < SWITCH_LOD and not pin.bLabelHidden:
            # 创建一个表示引脚框架的矩形
            frame = QtCore.QRectF(QtCore.QPointF(0, 0), pin.geometry().size())
            # 计算引脚半径的一半
            halfPinSize = pin.pinSize / 2
            # 设置字体为引脚的字体
            painter.setFont(pin._font)
            # 计算引脚显示名称的文本宽度
            textWidth = QtGui.QFontMetrics(painter.font()).horizontalAdvance(
                pin.displayName()
            )
            # 计算引脚显示名称的文本高度
            textHeight = QtGui.QFontMetrics(painter.font()).height()
            # 计算文本的 x 坐标
            x = 1 + pin.pinSize + halfPinSize
            # 检查引脚的方向是否为输出
            if pin.direction == PinDirection.Output:
                # 如果是输出引脚，重新计算 x 坐标
                x = frame.width() - textWidth - pin.pinSize - 1
            # 计算文本的 y 坐标
            yCenter = textHeight - textHeight / 3
            # 设置画笔为值引脚名称的画笔
            painter.setPen(PinPainter._valuePinNamePen)
            # 在指定位置绘制引脚名称
            painter.drawText(x, yCenter, pin.name)

            # 检查引脚是否处于悬停状态
            if pin.hovered:
                # 如果悬停，设置画笔为无画笔
                painter.setPen(QtCore.Qt.NoPen)
                # 设置画刷为半透明灰色
                painter.setBrush(QtGui.QColor(128, 128, 128, 30))
                # 绘制圆角矩形
                painter.drawRoundedRect(frame, 3, 3)

    @staticmethod
    def asDictPin(pin, painter, option, widget):
        """
        将引脚绘制为字典引脚。

        :param pin: 要绘制的引脚对象
        :param painter: 用于绘制的 QPainter 对象
        :param option: 绘制选项
        :param widget: 绘制的部件
        """
        # 获取引脚所属节点的画布细节级别
        lod = pin.owningNode().canvasRef().getCanvasLodValueFromCurrentScale()
        # 获取样式表中引脚切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().PinSwitch[0]
        # 计算每个网格单元的宽度
        cellW = pin.pinSize / 3
        # 计算每个网格单元的高度
        cellH = pin.pinSize / 3
        # 获取引脚的中心点
        pinCenter = pin.pinCenter()
        # 计算引脚半径的一半
        halfPinSize = pin.pinSize / 2

        # 设置画刷颜色为引脚颜色
        painter.setBrush(QtGui.QBrush(pin.color()))
        # 查找键类型对应的引脚类
        keyPin = findPinClassByType(pin._rawPin._keyType)
        # 创建一个黑色的画笔，线宽为 0.2
        painter.setPen(QtGui.QPen(QtCore.Qt.black, 0.2))
        # 遍历 3 行
        for row in range(3):
            # 计算 x 坐标
            x = pinCenter.x() - halfPinSize
            # 计算 y 坐标
            y = row * cellH + (halfPinSize / 2) + pin.pinCircleDrawOffset.y()
            # 设置画刷颜色为引脚颜色
            painter.setBrush(QtGui.QBrush(pin.color()))
            # 绘制矩形
            painter.drawRect(x + cellW, y, cellW * 2, cellH)
            # 检查是否找到键类型对应的引脚类
            if keyPin:
                # 如果找到，设置画刷颜色为键类型引脚的颜色
                painter.setBrush(QtGui.QBrush(QtGui.QColor(*keyPin.color())))
            # 绘制矩形
            painter.drawRect(x, y, cellW, cellH)

        # 检查细节级别是否小于阈值且引脚标签未隐藏
        if lod < SWITCH_LOD and not pin.bLabelHidden:
            # 创建一个表示引脚框架的矩形
            frame = QtCore.QRectF(QtCore.QPointF(0, 0), pin.geometry().size())
            # 计算引脚半径的一半
            halfPinSize = pin.pinSize / 2
            # 设置字体为引脚的字体
            painter.setFont(pin._font)
            # 计算引脚显示名称的文本宽度
            textWidth = QtGui.QFontMetrics(painter.font()).horizontalAdvance(
                pin.displayName()
            )
            # 计算引脚显示名称的文本高度
            textHeight = QtGui.QFontMetrics(painter.font()).height()
            # 计算文本的 x 坐标
            x = 1 + pin.pinSize + halfPinSize
            # 检查引脚的方向是否为输出
            if pin.direction == PinDirection.Output:
                # 如果是输出引脚，重新计算 x 坐标
                x = frame.width() - textWidth - pin.pinSize - 1
            # 计算文本的 y 坐标
            yCenter = textHeight - textHeight / 3
            # 设置画笔为值引脚名称的画笔
            painter.setPen(PinPainter._valuePinNamePen)
            # 在指定位置绘制引脚名称
            painter.drawText(x, yCenter, pin.name)

            # 检查引脚是否处于悬停状态
            if pin.hovered:
                # 如果悬停，设置画笔为无画笔
                painter.setPen(QtCore.Qt.NoPen)
                # 设置画刷为半透明灰色
                painter.setBrush(QtGui.QColor(128, 128, 128, 30))
                # 绘制圆角矩形
                painter.drawRoundedRect(frame, 3, 3)


# Determines how to paint a connection:
class ConnectionPainter(object):
    """
    该类包含静态方法，用于确定如何绘制不同类型的连接。
    """

    @staticmethod
    def linearPath(path, closed=False):
        """
        创建一个线性路径对象。

        :param path: 路径点列表
        :param closed: 是否闭合路径，默认为 False
        :return: 线性路径对象
        """
        # 创建一个路径对象
        mPath = QtGui.QPainterPath()
        # 移动到路径的第一个点
        mPath.moveTo(path[0])
        # 遍历路径的其他点
        for point in path[1:]:
            # 从当前位置绘制一条线到下一个点
            mPath.lineTo(point)
        return mPath

    @staticmethod
    def chanferPath(path, offset, closed=False):
        """
        创建一个带有倒角的路径。

        :param path: 路径点列表
        :param offset: 偏移量
        :param closed: 是否闭合路径，默认为 False
        :return: 带有倒角的路径点列表
        """
        # 初始化路径列表
        mPath = []
        # 遍历路径的每个点
        for i, point in enumerate(path):
            # 初始化前一个点、当前点和下一个点为当前点
            prevPoint = nextPoint = QtGui.QVector2D(point)
            currPoint = QtGui.QVector2D(point)
            # 检查是否不是最后一个点
            if i != len(path) - 1:
                # 如果不是最后一个点，获取下一个点
                nextPoint = QtGui.QVector2D(path[i + 1])
            # 检查是否闭合路径
            elif closed:
                # 如果闭合路径，获取第一个点
                nextPoint = QtGui.QVector2D(path[0])
            # 检查是否不是第一个点
            if i != 0:
                # 如果不是第一个点，获取前一个点
                prevPoint = QtGui.QVector2D(path[i - 1])
            # 检查是否闭合路径
            elif closed:
                # 如果闭合路径，获取最后一个点
                prevPoint = QtGui.QVector2D(path[-1])

            # 计算当前点到下一个点的向量
            fDist = nextPoint - currPoint
            # 计算当前点到前一个点的向量
            bDist = currPoint - prevPoint

            # 计算最大长度
            maxLen = max(0, min(fDist.length() / 2, (bDist.length()) / 2))

            # 计算点积
            dot = fDist.x() * bDist.x() + fDist.y() * bDist.y()  # dot product
            # 计算行列式
            det = fDist.x() * bDist.y() - fDist.y() * bDist.x()  # determinant
            # 计算夹角
            angle = degrees(atan2(det, dot))  # atan2(y, x) or atan2(sin, cos)

            # 检查夹角是否大于 45 度
            if abs(angle) > 45:
                # 如果大于 45 度，计算新的点
                n = currPoint + fDist.normalized() * maxLen
                p = currPoint - bDist.normalized() * maxLen
                # 处理不同位置的点
                if i == 0 and not closed:
                    mPath.append(point)
                elif i == 0 and closed:
                    mPath.append(QtCore.QPointF(p.x(), p.y()))
                    mPath.append(QtCore.QPointF(n.x(), n.y()))
                elif i != len(path) - 1 or closed:
                    mPath.append(QtCore.QPointF(p.x(), p.y()))
                    mPath.append(QtCore.QPointF(n.x(), n.y()))
                elif i == len(path) - 1 and not closed:
                    mPath.append(point)
                if i == len(path) - 1 and closed:
                    n = nextPoint - fDist.normalized() * maxLen
                    mPath.append(QtCore.QPointF(n.x(), n.y()))
            else:
                # 如果夹角小于等于 45 度，直接添加当前点
                mPath.append(point)

        return mPath

    @staticmethod
    def roundCornersPath(path, roundness, closed=False, highlightedSegment=-1):
        """
        创建一个带有圆角的路径。

        :param path: 路径点列表
        :param roundness: 圆角半径
        :param closed: 是否闭合路径，默认为 False
        :param highlightedSegment: 高亮线段的索引，默认为 -1
        :return: 带有圆角的路径对象和高亮线段的路径对象
        """
        # 创建一个路径对象
        mPath = QtGui.QPainterPath()
        # 创建一个高亮线段的路径对象
        highlightedSegmentPath = QtGui.QPainterPath()
        # 遍历路径的每个点
        for i, point in enumerate(path):
            # 初始化前一个点、当前点和下一个点为当前点
            prevPoint = nextPoint = QtGui.QVector2D(point)
            currPoint = QtGui.QVector2D(point)
            # 检查是否不是最后一个点
            if i != len(path) - 1:
                # 如果不是最后一个点，获取下一个点
                nextPoint = QtGui.QVector2D(path[i + 1])
            # 检查是否闭合路径
            elif closed:
                # 如果闭合路径，获取第一个点
                nextPoint = QtGui.QVector2D(path[0])
            # 检查是否不是第一个点
            if i != 0:
                # 如果不是第一个点，获取前一个点
                prevPoint = QtGui.QVector2D(path[i - 1])
            # 检查是否闭合路径
            elif closed:
                # 如果闭合路径，获取最后一个点
                prevPoint = QtGui.QVector2D(path[-1])

            # 计算当前点到下一个点的向量
            fDist = nextPoint - currPoint
            # 计算当前点到前一个点的向量
            bDist = currPoint - prevPoint

            # 计算圆角半径
            xRoundnes = min(min(roundness, fDist.length() / 2.0), bDist.length() / 2.0)

            # 计算新的点
            n = currPoint + fDist.normalized() * xRoundnes
            p = currPoint - bDist.normalized() * xRoundnes
            # 处理不同位置的点
            if i == 0 and not closed:
                mPath.moveTo(point)
            elif i == 0 and closed:
                mPath.moveTo(QtCore.QPointF(p.x(), p.y()))
                mPath.quadTo(point, QtCore.QPointF(n.x(), n.y()))

            elif i != len(path) - 1 or closed:
                mPath.lineTo(QtCore.QPointF(p.x(), p.y()))
                mPath.quadTo(point, QtCore.QPointF(n.x(), n.y()))

            elif i == len(path) - 1 and not closed:
                mPath.lineTo(point)
            if i == len(path) - 1 and closed:
                n = nextPoint - fDist.normalized() * xRoundnes
                mPath.lineTo(QtCore.QPointF(n.x(), n.y()))

            # 检查是否为高亮线段
            if i == highlightedSegment:
                if i != 0:
                    highlightedSegmentPath.moveTo(QtCore.QPointF(p.x(), p.y()))
                    highlightedSegmentPath.quadTo(point, QtCore.QPointF(n.x(), n.y()))
                else:
                    highlightedSegmentPath.moveTo(point)
                currPoint = QtGui.QVector2D(path[i + 1])
                nextPoint = QtGui.QVector2D(path[i + 2])
                prevPoint = QtGui.QVector2D(point.x(), point.y())
                fDist = nextPoint - currPoint
                bDist = currPoint - prevPoint
                xRoundnes = min(
                    min(roundness, fDist.length() / 2.0), bDist.length() / 2.0
                )

                n = currPoint + fDist.normalized() * xRoundnes
                p = currPoint - bDist.normalized() * xRoundnes
                highlightedSegmentPath.lineTo(QtCore.QPointF(p.x(), p.y()))
                highlightedSegmentPath.quadTo(
                    QtCore.QPointF(currPoint.x(), currPoint.y()),
                    QtCore.QPointF(n.x(), n.y()),
                )

        return mPath, highlightedSegmentPath

    @staticmethod
    def BasicCircuit(
            p1,
            p2,
            offset=20,
            roundness=5,
            sameSide=0,
            lod=0,
            complexLine=False,
            vOffset=0,
            hOffsetL=0,
            vOffsetSShape=0,
            hOffsetR=0,
            hOffsetRSShape=0,
            hOffsetLSShape=0,
            snapVToFirst=False,
            snapVToSecond=False,
            highlightedSegment=-1,
    ):
        """
        创建一个基本电路连接路径。

        :param p1: 起始点
        :param p2: 结束点
        :param offset: 偏移量，默认为 20
        :param roundness: 圆角半径，默认为 5
        :param sameSide: 是否在同一侧，默认为 0
        :param lod: 细节级别，默认为 0
        :param complexLine: 是否为复杂线条，默认为 False
        :param vOffset: 垂直偏移量，默认为 0
        :param hOffsetL: 左侧水平偏移量，默认为 0
        :param vOffsetSShape: S 形垂直偏移量，默认为 0
        :param hOffsetR: 右侧水平偏移量，默认为 0
        :param hOffsetRSShape: S 形右侧水平偏移量，默认为 0
        :param hOffsetLSShape: S 形左侧水平偏移量，默认为 0
        :param snapVToFirst: 是否垂直对齐到第一个点，默认为 False
        :param snapVToSecond: 是否垂直对齐到第二个点，默认为 False
        :param highlightedSegment: 高亮线段的索引，默认为 -1
        :return: 路径对象、路径点列表和高亮线段的路径对象
        """
        # 获取样式表中连接切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().ConnectionSwitch[0]
        # 初始化第一个点的偏移量
        offset1 = offset
        # 初始化第二个点的偏移量
        offset2 = -offset
        # 检查是否在同一侧
        if sameSide == 1:
            offset2 = offset
        elif sameSide == -1:
            offset1 = -offset

        # 计算两点之间的水平距离
        xDistance = (p2.x() + offset2) - (p1.x() + offset1)
        # 计算两点之间的垂直中点
        midPointY = p2.y() + ((p1.y() - p2.y()) / 2.0) + vOffsetSShape

        # 初始化路径点列表
        path = []
        # 添加起始点到路径点列表
        path.append(p1)
        # 检查水平距离是否大于 0 或在不同侧
        if xDistance > 0 or sameSide == -1:
            # 检查是否垂直对齐到第二个点
            if snapVToSecond:
                # 如果垂直对齐到第二个点，计算垂直偏移量
                vOffset = p2.y() - p1.y()
            # 检查是否垂直对齐到第一个点
            elif snapVToFirst:
                # 如果垂直对齐到第一个点，垂直偏移量为 0
                vOffset = 0

            # 检查是否不垂直对齐到第一个点
            if not snapVToFirst:
                # 如果不垂直对齐到第一个点，更新第一个点的水平偏移量
                offset1 += hOffsetL
            # 检查是否不垂直对齐到第二个点
            if not snapVToSecond:
                # 如果不垂直对齐到第二个点，更新第二个点的水平偏移量
                offset2 += hOffsetR

            # 检查垂直偏移量是否大于 0
            if abs(vOffset) > 0:
                # 如果垂直偏移量大于 0，添加路径点
                path.append(QtCore.QPointF(p1.x() + offset1, p1.y()))
                path.append(QtCore.QPointF(p1.x() + offset1, p1.y() + vOffset))

            # 添加路径点
            path.append(QtCore.QPointF(p2.x() + offset2, p1.y() + vOffset))
            path.append(QtCore.QPointF(p2.x() + offset2, p2.y()))
            path.append(p2)
        else:
            # 如果水平距离小于等于 0 且在同一侧，更新偏移量
            offset1 += hOffsetRSShape
            offset2 += hOffsetLSShape
            # 添加路径点
            path.append(QtCore.QPointF(p1.x() + offset1, p1.y()))
            path.append(QtCore.QPointF(p1.x() + offset1, midPointY))
            path.append(QtCore.QPointF(p2.x() + offset2, midPointY))
            path.append(QtCore.QPointF(p2.x() + offset2, p2.y()))
            path.append(p2)

        # 检查是否为复杂线条
        if complexLine:
            # 如果是复杂线条，调用 chanferPath 方法处理路径
            path = ConnectionPainter.chanferPath(path, offset)

        # 初始化高亮线段的路径对象为 None
        section = None
        # 检查细节级别是否大于等于阈值
        if lod >= SWITCH_LOD:
            # 如果大于等于阈值，调用 linearPath 方法创建线性路径
            mPath = ConnectionPainter.linearPath(path)
        else:
            # 如果小于阈值，调用 roundCornersPath 方法创建带有圆角的路径
            mPath, section = ConnectionPainter.roundCornersPath(
                path, roundness, highlightedSegment=highlightedSegment
            )
        return mPath, path, section

    @staticmethod
    def Cubic(p1, p2, defOffset=150, lod=0):
        """
        创建一个三次贝塞尔曲线连接路径。

        :param p1: 起始点
        :param p2: 结束点
        :param defOffset: 默认偏移量，默认为 150
        :param lod: 细节级别，默认为 0
        :return: 三次贝塞尔曲线路径对象
        """
        # 获取样式表中连接切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().ConnectionSwitch[0]
        # 创建一个路径对象
        mPath = QtGui.QPainterPath()

        # 计算两点之间的水平距离
        xDistance = p2.x() - p1.x()
        # 计算两点之间的垂直距离
        vDistance = p2.y() - p1.y()
        # 计算偏移量
        offset = abs(xDistance) * 0.5
        # 检查水平距离是否小于默认偏移量
        if abs(xDistance) < defOffset:
            # 如果小于默认偏移量，更新偏移量
            offset = defOffset / 2
        # 检查垂直距离是否小于 20
        if abs(vDistance) < 20:
            # 如果小于 20，更新偏移量
            offset = abs(xDistance) * 0.3
        # 移动到起始点
        mPath.moveTo(p1)
        # 检查细节级别是否大于等于阈值
        if lod >= SWITCH_LOD:
            # 如果大于等于阈值，更新偏移量
            offset = 20
        # 检查水平距离是否小于 0
        if xDistance < 0:
            # 如果小于 0，计算控制点 1
            cp1 = QtCore.QPointF(p1.x() + offset, p1.y())
            # 计算控制点 2
            cp2 = QtCore.QPointF(p2.x() - offset, p2.y())
        else:
            # 如果大于等于 0，计算控制点 2
            cp2 = QtCore.QPointF(p2.x() - offset, p2.y())
            # 计算控制点 1
            cp1 = QtCore.QPointF(p1.x() + offset, p1.y())
        # 检查细节级别是否大于等于阈值
        if lod >= SWITCH_LOD:
            # 如果大于等于阈值，调用 linearPath 方法创建线性路径
            mPath = ConnectionPainter.linearPath([p1, cp1, cp2, p2])
        else:
            # 如果小于阈值，创建三次贝塞尔曲线
            mPath.cubicTo(cp1, cp2, p2)

        return mPath

    @staticmethod
    def Linear(p1, p2, defOffset=150, roundness=5, lod=0):
        """
        创建一个线性连接路径。

        :param p1: 起始点
        :param p2: 结束点
        :param defOffset: 默认偏移量，默认为 150
        :param roundness: 圆角半径，默认为 5
        :param lod: 细节级别，默认为 0
        :return: 线性连接路径对象
        """
        # 获取样式表中连接切换的细节级别阈值
        SWITCH_LOD = editableStyleSheet().ConnectionSwitch[0]

        # 计算控制点 1
        cp1 = QtCore.QPointF(p1.x() + defOffset, p1.y())
        # 计算控制点 2
        cp2 = QtCore.QPointF(p2.x() - defOffset, p2.y())

        # 检查细节级别是否大于等于阈值
        if lod >= SWITCH_LOD:
            # 如果大于等于阈值，调用 linearPath 方法创建线性路径
            mPath = ConnectionPainter.linearPath([p1, cp1, cp2, p2])
        else:
            # 如果小于阈值，调用 roundCornersPath 方法创建带有圆角的路径
            mPath = ConnectionPainter.roundCornersPath([p1, cp1, cp2, p2], roundness)

        return mPath